package counter.counter;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import counter.info.CounterResultInfo;
import counter.info.FileTypeInfo;
import counter.utils.FileUtils;

public final class Counter {
    private static Counter INSTANCE;// = new Counter();

    private CounterResultInfo counterInfo;

    Map<String, FileTypeInfo> fileTypes;

    List<String> inclusiveExtensionsList =
        Arrays.asList(new String[] {"xml", "java", "jspx", "sql", "xsd", "html", "xsl", "txt", "jsp",
        "css"});

    List<String> exclusiveFoldersList =
    //    Arrays.asList(new String[] {"D:\\snapshot\\amarkin_Pu3.2.0-MW_dev_2\\pluto\\build"});
        Arrays.asList(new String[] {"D:\\snapshot\\amarkin_CnTRNK-MW_dev\\canine\\build"});

    private Counter() {
    }

    public static synchronized Counter getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new Counter();
        }
        return INSTANCE;
    }

    public void calculate(final String rootfolder) {
        fileTypes = new TreeMap<String, FileTypeInfo>();
        List<String> innerFolderNames = getInnerFolders(new ArrayList<String>() {
            {
                add(rootfolder);
            }
        });

        for (String f : innerFolderNames) {
            File[] innerFiles = new File(f).listFiles();
            for (int i = 0; i < innerFiles.length; i++) {
                if (!innerFiles[i].isDirectory()) {
                    processFile(innerFiles[i]);
                }
            }
        }
        counterInfo = new CounterResultInfo();
        counterInfo.setFilesInfo(new ArrayList<FileTypeInfo>());
        for (Map.Entry<String, FileTypeInfo> entry : fileTypes.entrySet()) {
            counterInfo.getFilesInfo().add(entry.getValue());
        }
        counterInfo.setRootFolder(rootfolder);
    }

    private List<String> getInnerFolders(List<String> folders) {
        List<String> innerFolders = new ArrayList<String>();
        for (String folder : folders) {
            File[] innerFile = new File(folder).listFiles();
            for (int i = 0; i < innerFile.length; i++) {
                if (innerFile[i].isDirectory() && !exclusiveFoldersList.contains(innerFile[i].getAbsolutePath())) {
                    innerFolders.add(innerFile[i].getPath());
                }
            }
        }
        if (!innerFolders.isEmpty()) {
            folders.addAll(getInnerFolders(innerFolders));
        }
        return folders;
    }

    private FileTypeInfo getFileType(String ext) {
        if (!fileTypes.containsKey(ext)) {
            fileTypes.put(ext, new FileTypeInfo(ext));
        }
        return fileTypes.get(ext);
    }

    private void processFile(File file) {
        String fileExtension = FileUtils.getFileExtension(file);
        if (inclusiveExtensionsList.contains(fileExtension)) {
            FileTypeInfo fileTypeInfo = getFileType(FileUtils.getFileExtension(file));
            fileTypeInfo.incLinesNumber(FileUtils.getLoC(file));
            fileTypeInfo.incFilesNumber();
        }
    }

    public CounterResultInfo getCounterInfo() {
        return counterInfo;
    }

    public void setCounterInfo(CounterResultInfo counterInfo) {
        this.counterInfo = counterInfo;
    }
}
